package mail;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class Main {

	public static void readMail() {
		// read header
		readHeader();

		// extract attachment
		extractAttachment();
	}

	public static void readHeader() {
		System.out.println("READ HEADER");
	}

	public static void extractAttachment() {
		System.out.println("EXTRACT ATTACHMENT");
	}

	public static void main(String[] args) {
		String subject, text, destinataire, copyDest;
		subject = "Sujet";
		text = "Texte";
		destinataire = "xou.xavl@gmail.com";
		copyDest = destinataire;

		/*
		 * Phase d'envoi
		 */
		// Test message : texte uniquement
		// sendMessage(subject, text, destinataire, copyDest, null);

		// Test message : texte & piece jointe
		// sendMessageAttachement();

		/*
		 * Phase de lecture
		 */
		// handleMessageAttachment();

		// AUTRE PISTE
		// try {
		// display(new File("/home/lutecia/Desktop/test.eml"));
		// } catch (Exception e) {
		// e.getMessage();
		// }

		/*
		 * 
		 */
		try {
//			mainTEST(null);
			new Mail().mainTEST(null);
		} catch (Exception e) {
			e.getMessage();
		}
	}

	public static void sendMessage(String subject, String text,
			String destinataire, String copyDest, MimeMultipart attachment) {
		// 1 -> Création de la session
		Properties properties = new Properties();
		properties.setProperty("mail.transport.protocol", "smtp");
		properties.setProperty("mail.smtp.host", "smtp.gmail.com");
		properties.setProperty("mail.smtp.user", "xou.xavl@gmail.com");
		properties.setProperty("mail.from", "imap.gmail.com");
		properties.setProperty("mail.smtp.starttls.enable", "true");
		properties.setProperty("mail.smtp.port", "587");

		Session session = Session.getInstance(properties);

		// 2 -> Création du message
		MimeMessage message = new MimeMessage(session);
		try {
			message.setText(text);
			message.setSubject(subject);
			if (attachment != null)
				message.setContent(attachment);
			message.addRecipients(Message.RecipientType.TO, destinataire);
			message.addRecipients(Message.RecipientType.CC, copyDest);

			System.out
					.println("Port: " + session.getProperty("mail.smtp.port"));

		} catch (MessagingException e) {
			e.printStackTrace();
		}

		// 3 -> Envoi du message
		Transport transport = null;
		try {
			transport = session.getTransport("smtp");
			transport.connect("xou.xavl@gmail.com", "");
			transport.sendMessage(message, new Address[] {
					new InternetAddress("xou.xavl@gmail.com"),
					new InternetAddress("xou.xavl@gmail.com") });
			System.out.println("Transport: " + transport.toString());
		} catch (MessagingException e) {
			e.printStackTrace();
		} finally {
			try {
				if (transport != null) {
					transport.close();
				}
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		}
	}

	public static void sendMessageAttachement() {
		// part 1
		File file = new File("/home/lutecia/Desktop/pingouin.png");
		FileDataSource datasource1 = new FileDataSource(file);
		DataHandler handler1 = new DataHandler(datasource1);
		MimeBodyPart autruche = new MimeBodyPart();
		try {
			autruche.setDataHandler(handler1);
			autruche.setFileName(datasource1.getName());
			System.out.println("Part 1 handled");
		} catch (MessagingException e) {
			e.printStackTrace();
		}

		// part 2
		MimeBodyPart content = new MimeBodyPart();
		try {
			content.setContent("Texte du message", "text/plain");
			System.out.println("Part 2 handle");
		} catch (MessagingException e) {
			e.printStackTrace();
		}

		// stores part 1 and 2
		MimeMultipart mimeMultipart = new MimeMultipart();
		try {
			mimeMultipart.addBodyPart(content);
			mimeMultipart.addBodyPart(autruche);
			System.out.println("All parts gathered");
		} catch (MessagingException e) {
			e.printStackTrace();
		}

		// message creation and sending
		System.out.println("Start sending...");
		sendMessage("Test attachment", "this email contains an image",
				"xou.xavl@gmail.com", "xou.xavl@gmail.com", mimeMultipart);
		System.out.println("End sending.");
	}

	public static void handleMessageAttachment() {
		System.out.println("Extract attachement");
		receivePop3(2);
	}

	public static void printMessageAttachment(Message message) {
		try {
			DataSource dataSource = message.getDataHandler().getDataSource();
			MimeMultipart mimeMultipart = new MimeMultipart(dataSource);
			int multiPartCount = mimeMultipart.getCount();
			System.out.println("Il y a " + multiPartCount
					+ " partie(s) dans ce message.");

			for (int i = 0; i < multiPartCount; i++) {
				BodyPart bp = mimeMultipart.getBodyPart(i);
				processBodyPart(bp);
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}

	public static void printMessageAttachmentBeta(Message message) {
		try {
			DataSource dataSource = message.getDataHandler().getDataSource();
			MimeMultipart mimeMultipart = new MimeMultipart(dataSource);
			int multiPartCount = mimeMultipart.getCount();
			System.out.println("Il y a " + multiPartCount
					+ " partie(s) dans ce message.");

			for (int i = 0; i < multiPartCount; i++) {
				BodyPart bp = mimeMultipart.getBodyPart(i);
				processBodyPart(bp);
			}
		} catch (MessagingException e) {
			e.printStackTrace();
		}
	}

	private static void processBodyPart(BodyPart bp) {
		try {
			System.out.println("Type : " + bp.getContentType());
			String fileName = bp.getFileName();
			System.out.println("FileName : " + fileName);

			if (bp.isMimeType("text/plain")) {
				System.out.println("Texte du message :");
				FileInputStream fis = new FileInputStream(
						"/home/lutecia/Desktop/contenu.txt");
				StringBuilder inputStringBuilder = new StringBuilder();
				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(fis, "UTF-8"));
				// BufferedReader bufferedReader = new BufferedReader(
				// new InputStreamReader(bp.getInputStream()));
				String line = bufferedReader.readLine();
				while (line != null) {
					inputStringBuilder.append(line);
					inputStringBuilder.append('\n');
					line = bufferedReader.readLine();
				}
				bufferedReader.close();
				System.out.println(inputStringBuilder.toString());
			} else {
				System.out.println("CONTIENT DES ATTACHEMENTS");
				test(bp);
				System.out.println("START : traitement");
				DataHandler dh = bp.getDataHandler();
				File file = new File("/home/lutecia/Desktop/" + fileName);
				FileOutputStream fos = new FileOutputStream(file);
				dh.writeTo(fos);
			}
		} catch (MessagingException e) {
			System.out.println("TRY/CATCH -- message --");
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// ====

	public static void receivePop3(int messageToReceive) {
		Properties properties = new Properties();
		properties.setProperty("mail.store.protocol", "imaps");
		properties.setProperty("mail.imap.host", "imap.googlemail.com");
		properties.setProperty("mail.imap.user", "xou.xavl@gmail.com");
		properties.setProperty("mail.imap.starttls.enable", "true");
		properties.setProperty("mail.imap.port", "993");

		System.out.println("settings ok");

		Session session = Session.getInstance(properties);
		Store store = null;
		Folder defaultFolder = null;
		Folder inbox = null;
		try {
			store = session.getStore("imaps");
			store.connect("imap.gmail.com", 993, "xou.xavl@gmail.com",
					"");
			defaultFolder = store.getDefaultFolder();
			System.out.println("defaultFolder : " + defaultFolder.getName());
			for (Folder folder : defaultFolder.list()) {
				System.out.println(folder.getName());
			}

			inbox = defaultFolder.getFolder("INBOX");
			printMessages(inbox, messageToReceive);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			close(inbox);
			close(defaultFolder);
			try {
				if (store != null && store.isConnected()) {
					store.close();
				}
			} catch (MessagingException e) {
				e.printStackTrace();
			}
		}

	}

	private static void close(Folder folder) {
		if (folder != null && folder.isOpen()) {
			try {
				folder.close(false); // false -> On n'efface pas les messages
										// marqués DELETED
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private static void printMessages(Folder folder, int messageToReceive) {
		try {
			folder.open(Folder.READ_ONLY);
			int count = folder.getMessageCount();
			int unread = folder.getUnreadMessageCount();
			System.out.println("Il y a " + count + " messages, dont " + unread
					+ " non lus.");
			if (messageToReceive > count) {
				messageToReceive = count;
			}
			for (int i = 0; i < messageToReceive; i++) {
				int messageNumber = count - i;
				Message message = folder.getMessage(messageNumber);
				System.out.println("Message n° " + messageNumber);
				System.out.println("Sujet : " + message.getSubject());

				System.out.println("Expéditeur : ");
				Address[] addresses = message.getFrom();
				for (Address address : addresses) {
					System.out.println("\t" + address);
				}

				System.out.println("Destinataires : ");
				addresses = message.getRecipients(RecipientType.TO);
				for (Address address : addresses) {
					System.out.println("\tTo : " + address);
				}
				addresses = message.getRecipients(RecipientType.CC);
				if (addresses != null)
					for (Address address : addresses) {
						System.out.println("\tCopie : " + address);
					}

				if (message.isMimeType("multipart/mixed")) {
					// HARVEST >>
					Properties prop = new Properties();
					Session session = Session.getInstance(prop);

					FileInputStream fis = new FileInputStream(
							"/home/lutecia/Desktop/test.txt");
					MimeMessage mail = new MimeMessage(session, fis);
					fis.close();

					printMessageAttachmentBeta(mail);
					// HARVEST <<
					// printMessageAttachment(message);
				} else {
					System.out.println("Content : ");

					StringBuilder inputStringBuilder = new StringBuilder();
					// BufferedReader bufferedReader = new BufferedReader(new
					// InputStreamReader(fis, "UTF-8"));
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(message.getInputStream()));
					String line = bufferedReader.readLine();
					while (line != null) {
						inputStringBuilder.append(line);
						inputStringBuilder.append('\n');
						line = bufferedReader.readLine();
					}
					System.out.println(inputStringBuilder.toString());
					System.out.println("-------------");
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void test(BodyPart bp) {
		try {
			String name = bp.getFileName();
			if (bp.isMimeType("application/octet-stream")) {
				System.out.println("MIME : OCTET");
			} else {
				System.out.println("OCTET : KO");
			}
			if (bp.isMimeType("text/plain")) {
				System.out.println("MIME : PLAIN");
			} else {
				System.out.println("PLAIN : KO");
			}
			System.out.println("NAME : " + name);
			if (name.contentEquals("edi")) {
				System.out.println("TROUVE");
			}
		} catch (Exception e) {
			e.getMessage();
		}
	}

	// ===

	public static void display(File emlFile) throws Exception {
		Properties props = System.getProperties();
		props.put("mail.host", "smtp.dummydomain.com");
		props.put("mail.transport.protocol", "smtp");

		Session mailSession = Session.getDefaultInstance(props, null);
		InputStream source = new FileInputStream(emlFile);
		MimeMessage message = new MimeMessage(mailSession, source);

		System.out.println("Subject : " + message.getSubject());
		System.out.println("From : " + message.getFrom()[0]);
		System.out.println("--------------");
		System.out.println("Body : " + message.getContent());

		printMessageAttachment(message);
	}

	// ==

	public static void mainTEST(String args[]) throws Exception {
		File emlFile = new File("/home/lutecia/Desktop/test.eml");

		InputStream source = new FileInputStream(emlFile);

		Properties props = System.getProperties();
		props.put("mail.host", "smtp.dummydomain.com");
		props.put("mail.transport.protocol", "smtp");

		Session mailSession = Session.getDefaultInstance(props, null);
		MimeMessage message = new MimeMessage(mailSession, source);
		Multipart multipart = (Multipart) message.getContent();
		System.out.println("NB part : " + multipart.getCount());
		System.out.println();

		for (int x = 0; x < multipart.getCount(); x++) {
			BodyPart bodyPart = multipart.getBodyPart(x);
			
			System.out.println("============================");
			String des = bodyPart.getDescription();
			System.out.println("Description : " + des);
			System.out.println("============================");

			String disposition = bodyPart.getDisposition();
			System.out.println("Disposition : " + disposition);

			if (disposition != null && (disposition.equals(BodyPart.ATTACHMENT))) {
				DataHandler handler = bodyPart.getDataHandler();
				String type = handler.getContentType();
				String fileName = handler.getName();
				System.out.println("file name : " + fileName);
				System.out.println("file type : " + type);
				File file = new File("/home/lutecia/Desktop/" + fileName);
				FileOutputStream fos = new FileOutputStream(file);
				handler.writeTo(fos);
			} else {
				System.out.println(bodyPart.getContent());
				if (disposition == null) {
					Multipart multipart2 = (Multipart) bodyPart.getContent();
					System.out.println("NB part : " + multipart2.getCount());
					
					for (int j = 0; j < multipart2.getCount(); j++) {
						BodyPart bodyPart2 = multipart2.getBodyPart(j);
						
						System.out.println("============================");
						String des2 = bodyPart2.getDescription();
						System.out.println("Description : " + des2);
						System.out.println("============================");

						String disposition2 = bodyPart2.getDisposition();
						System.out.println("Disposition : " + disposition2);
						if (disposition2 != null && (disposition2.equals(BodyPart.ATTACHMENT))) {
							DataHandler handler = bodyPart2.getDataHandler();
							String type = handler.getContentType();
							String fileName = handler.getName();
							System.out.println("file name : " + fileName);
							System.out.println("file type : " + type);
							File file = new File("/home/lutecia/Desktop/" + fileName);
							FileOutputStream fos = new FileOutputStream(file);
							handler.writeTo(fos);
						}
					}
				}
			}
		}
		System.out.println();
	}
}
